import mailbox
import email
import datetime
import time
from optparse import OptionParser

from src.archive import Archive

def prepare(filename, min_replys):
    email_archive = Archive(filename)
    email_list = email_archive.parse()
    email_tree = email_archive.make_tree(email_list)
    
    thread_roots_node = email_tree.root.children
    
    reply_emails = []
    
    # function used in pre-order walk 
    def get_from_header(node):
        if not node in thread_roots_node:
            email_name = email.utils.parseaddr(node.elem["from"])[0]
            email_address = email.utils.parseaddr(node.elem["from"])[1]
            
            # special case for Lucene Apache mailing list project
            if email_address == "jira@apache.org":
                reply_emails.append("\"" + email_name + "\" " + email_address)
            else:
                reply_emails.append(email_address)
    
    for msg_node in thread_roots_node:
        email_tree.pre_order(get_from_header, msg_node) # get replys
        
        if (len(reply_emails) >= min_replys):
            
            file_number = str(int(time.time() * 1000000))
            msg = msg_node.elem
            
            question_file = open(file_number + ".question", "w")
            question_file.write(msg["from"]+"\n")
            
            date_tuple = email.utils.parsedate_tz(msg["date"])
            
            if date_tuple:
                question_file.write("%02d/%02d/%d\n" % (date_tuple[2], date_tuple[1], date_tuple[0]))
            else:
                question_file.write("No date specified\n")
            
            question_file.write(msg["subject"]+"\n")
            
            # a payload may be a string or a list of messages
            payload = msg.get_payload()
            
            if isinstance(payload, list):
                # merge the messages in one string
                payload = reduce(lambda x,y: str(x)+"\n"+str(y), payload)
            
            # using str to avoid a weird "instance" type return 
            question_file.write(str(payload))
            
            reply_file = open(file_number + ".emails", "w")
            reply_file.write("\n".join(reply_emails))
        
        reply_emails = []

def remove(email_addr, filename_in, filename_out):
    email_archive = Archive(filename_in)
    email_list = email_archive.parse()
    email_tree = email_archive.make_tree(email_list)
    
    # getting only the messages that match with email_addr
    match_list = []
    
    def get_email(node):
        if node.elem != None: #dummy root
            if email.utils.parseaddr(node.elem["from"])[1] == email_addr:
                match_list.append(node)
    
    email_tree.pre_order(get_email)
    
    # removing nodes 
    for node in match_list:
        while node.parent != None:
            node = node.parent
        
        email_tree.root.children.remove(node)
        
    # getting all remained nodes
    node_list = []
    
    def get_all_nodes(node):
        if node.elem != None: #dummy root
            node_list.append(node)
        
    email_tree.pre_order(get_all_nodes)
        
    # creating a new mbox
    result_mbox = mailbox.mbox(filename_out)
    
    for node in node_list:
        result_mbox.add(node.elem)
        result_mbox.flush()
    

if __name__ == "__main__":
    parser = OptionParser()
    parser.add_option("-p", "--prepare", dest="mboxfile")
    parser.add_option("-n", dest="min_replys", default=1)
    parser.add_option("-r", "--remove", dest="removeargs", nargs=3)

    (opts, args) = parser.parse_args()
    
    if opts.mboxfile:
        try:
            prepare(opts.mboxfile, int(opts.min_replys))
        except IOError:
            print "Error: file %s not found" % opts.mboxfile
    elif opts.removeargs:
        try:
            remove(*opts.removeargs)
        except IOError:
            print "Error: file %s not found" % opts.removeargs[1]